#pragma once

#include <boostext/util/make_shared.hpp>
#include <engine.core/math.hpp>

#include "exports.hpp"




namespace Engine
{
	namespace Video
	{
		struct Filter
		{
			enum Type
			{
				MinMagMipPoint,
				MinMagPointMipLinear,
				MinPointMagLinearMipPoint,
				MinPointMagMipLinear,
				MinLinearMagMipPoint,
				MinLinearMagPointMipLinear,
				MinMagLinearMipPoint,
				MinMagMipLinear,
				Anisotropic,
			};
		};
		///////////////////////////////////////////////////////////////////////////////////////////////////

		struct Address
		{
			enum Type
			{
				Wrap,
				Mirror,
				Clamp,
				Border,
				MirrorOnce,
			};
		};
		///////////////////////////////////////////////////////////////////////////////////////////////////

		struct Comparison
		{
			enum Type
			{
				Never,
				Less,
				Equal,
				LessEqual,
				Greater,
				NotEqual,
				GreaterEqual,
				Always,
			};
		};
		///////////////////////////////////////////////////////////////////////////////////////////////////




		class ENGINE_VIDEO_API SamplerState
		{
		public:

			SHARED(SamplerState);

			/**
			 * Set the texture filter to use when sampling a texture.
			 * @see Filter::Type
			 */
			virtual void setFilter(Filter::Type filter) = 0;

			/**
			 * Method to use for resolving a u texture coordinate that is outside the 0 to 1 range.
			 * @see Address::Type
			 */
			virtual void setAddressU(Address::Type address) = 0;

			/**
			 * Method to use for resolving a v texture coordinate that is outside the 0 to 1 range.
			 * @see Address::Type
			 */
			virtual void setAddressV(Address::Type address) = 0;

			/**
			 * Method to use for resolving a w texture coordinate that is outside the 0 to 1 range.
			 * @see Address::Type
			 */
			virtual void setAddressW(Address::Type address) = 0;

			/**
			 * Offset from the calculated mipmap level. For example, if Direct3D calculates
			 * that a texture should be sampled at mipmap level 3 and MipLODBias is 2, then
			 * the texture will be sampled at mipmap level 5.
			 */
			virtual void setMipLODBias(float bias) = 0;

			/**
			 * Clamping value used if Filter::Anisotropic is specified in Filter.
			 * Valid values are between 1 and 16.
			 */
			virtual void setMaxAnisotropy(uint32 max) = 0;

			/**
			 * A function that compares sampled data against existing sampled data.
			 * @see Comparison::Type
			 */
			virtual void setComparisonFunc(Comparison::Type func) = 0;

			/**
			 * Lower end of the mipmap range to clamp access to, where 0 is the largest
			 * and most detailed mipmap level and any level higher than that is less detailed.
			 */
			virtual void setMinLOD(float min) = 0;

			/**
			 * Upper end of the mipmap range to clamp access to, where 0 is the largest and
			 * most detailed mipmap level and any level higher than that is less detailed.
			 * This value must be greater than or equal to MinLOD. To have no upper limit on
			 * LOD set this to a large value such as std::numeric_limits<float>::max().
			 */
			virtual void setMaxLOD(float max) = 0;

			/**
			 * Border color to use if D3D11_TEXTURE_ADDRESS_BORDER is specified for AddressU, 
			 * AddressV, or AddressW. Range must be between 0.0 and 1.0 inclusive. 
			 */
			virtual void setBorderColor(const float4& color) = 0;



			/**
			 * Get the filter method to use when sampling a texture.
			 */
			virtual Filter::Type filter() const = 0;

			/**
			 * Get the method for resolving a u texture coordinate that is outside the 0 to 1 range.
			 */
			virtual Address::Type addressU() const = 0;

			/**
			 * Get the method for resolving a v texture coordinate that is outside the 0 to 1 range.
			 */
			virtual Address::Type addressV() const = 0;

			/**
			 * Get the method for resolving a w texture coordinate that is outside the 0 to 1 range.
			 */
			virtual Address::Type addressW() const = 0;

			/**
			 * Get the offset for the calculated mipmap level.
			 */
			virtual float mipLODBias() const = 0;

			/**
			 * Get the clamping value for the anisotropy filter.
			 */
			virtual uint32 maxAnisotropy() const = 0;

			/**
			 * Get the comparison function that compares the sampled data against existing data.
			 */
			virtual Comparison::Type comparisonFunc() const = 0;

			/**
			 * Get the lower end of the mipmap range to clamp access to.
			 */
			virtual float minLOD() const = 0;

			/**
			 *Get the upper end of the mipmap range to clamp access to.
			 */
			virtual float maxLOD() const = 0;

			/**
			 * Get the border color.
			 */
			virtual float4 borderColor() const = 0;
		};
		///////////////////////////////////////////////////////////////////////////////////////////
	}
	///////////////////////////////////////////////////////////////////////////////////////////////
}
///////////////////////////////////////////////////////////////////////////////////////////////////
